using System;
using System.Windows.Forms;

namespace Linquid.Controls
{	
	/// <summary>
	/// Source generators for controls.
	/// </summary>
	public static class ControlExtensions
	{
		private static Source<Nothing> Event(Action<EventHandler> bind)
		{
			var source = new Source<Nothing>();
			bind((s, a) => source.SetValue(Nothing.Empty));
			return source;
		}
		
		private static Source<A> Value<A>(Func<A> value, Action<Action> bind)
		{
			var source = new Source<A>(value());
			bind(() => source.SetValue(value()));
			return source;
		}
		
		/// <summary>
		/// Creates a source from the control's TextChanged event.
		/// </summary>
		/// <param name="control">Control, which event is used to create the source.</param>
		/// <returns>Source of control's text.</returns>
		public static Source<string> TextSource(this Control control)
		{
			return Value(() => control.Text,
			             handler => control.TextChanged += delegate {handler();});			
		}
		
		/// <summary>
		/// Creates a source from the control's EnabledChanged event.
		/// </summary>
		/// <param name="control">Control, which event is used to create the source.</param>
		/// <returns>Source of control's enabled state.</returns>
		public static Source<bool> EnabledSource(this Control control)
		{
			return Value(() => control.Enabled,
			             handler => control.EnabledChanged += delegate {handler();});			
		}
				
		/// <summary>
		/// Creates a source from the control's Click event.
		/// </summary>
		/// <param name="control">Control, which event is used to create the source.</param>
		/// <returns>Source which is updated when control is clicked.</returns>
		public static Source<Nothing> ClickSource(this Control control)
		{
			return Event(handler => control.Click += handler);
		}

		/// <summary>
		/// Creates a source from the control's DoubleClick event.
		/// </summary>
		/// <param name="control">Control, which event is used to create the source.</param>
		/// <returns>Source which is updated when control is double clicked.</returns>
		public static Source<Nothing> DoubleClickSource(this Control control)
		{
			return Event(handler => control.DoubleClick += handler);
		}
		
		/// <summary>
		/// Creates a source from the control's GotFocus event.
		/// </summary>
		/// <param name="control">Control, which event is used to create the source.</param>
		/// <returns>Source which is updated when control is focused.</returns>
		public static Source<Nothing> FocusSource(this Control control)
		{
			return Event(handler => control.GotFocus += handler);
		}
	}
}